package main

import "fmt"

// 接口的定义
//	type 接口名 interface {
//		方法名1(参数1, 参数2...)(返回值1, 返回值2...)
//		...
//	}

// 一个结构体 如果实现了 接口中规定的所有方法
// 那么这个结构体 就 实现了这个接口, 也就是 java中 接口的 实现类
// 多个类型可以实现一个接口
// 一个类型可以实现多个接口
// 接口 可以嵌套 接口

// Empty 空接口
//type Empty interface { ... }
// 空接口 没有必要命名 可定义成以下形式
//interface{}
// 作为函数参数使用时 可传入任意类型变量

// Speaker 定义一个能叫的 类型 接口
type Speaker interface {
	// Cell
	// 接口内部 声明 方法签名
	// 只要实现了 Cell 方法 都是 Speaker 类型
	Cell()
}

// Animal 接口 嵌套
type Animal interface {
	Speaker
}

type Cat struct {
}

// Cell 实现的 方法签名 必须 与接口 规定的一致
func (c *Cat) Cell() {
	fmt.Printf("猫：叫\n")
}

type Dog struct {
}

func (d *Dog) Cell() {
	fmt.Printf("狗：叫\n")
}

// Call
// 叫 谁 谁回应
func Call(speaker Animal) {
	speaker.Cell()
}

// 空接口作为参数
func print(i interface{}) {
	fmt.Printf("%T %#v", i, i)
}

func main() {
	c1 := new(Cat)
	d1 := new(Dog)

	Call(c1)
	Call(d1)

	fmt.Println("=========================================================")

	// 定义一个 Speaker 接口类型的变量
	var speaker Speaker

	speaker = c1
	Call(speaker)

	speaker = d1
	Call(speaker)

	fmt.Println("=========================================================")

	print(c1)
	print(d1)
}
